package com.bstek.pms.tools.view.db.doccreate;

import com.bstek.pms.tools.model.DBProperties;
import com.bstek.pms.tools.model.Schema;
import com.bstek.pms.tools.model.TableInfo;
import com.bstek.pms.tools.service.DBInfoService;
import com.bstek.pms.tools.service.ExportDocument;
import com.bstek.pms.tools.service.SchemaService;
import com.bstek.pms.tools.service.impl.ExportDocumentForMultipleExcel;
import com.bstek.pms.tools.service.impl.ExportDocumentForOneExcel;
import com.bstek.pms.tools.service.impl.ExportDocumentForWord;
import com.bstek.pms.tools.utils.AlertUtils;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.net.URL;
import java.util.*;

/**
 * @Description 数据库表结构导出控制类
 * @Author hans
 * @CreateDate 2020-6-27
 */
@Controller
public class TabDBDocCreateController implements Initializable {
    private Logger logger=Logger.getLogger(TabDBDocCreateController.class);


    @Autowired
    private SchemaService schemaService;

    private ExportDocument exportDocument;

    @FXML
    private TableView<TableInfo> tables;

    @FXML
    private TableColumn<TableInfo, String> id;

    @FXML
    private TableColumn<TableInfo, CheckBox> chose;

    @FXML
    private TableColumn<TableInfo,String> tableName;

    @FXML
    private TableColumn<TableInfo,String> tabConment;

    @FXML
    private TextField txtDbUrl;

    @FXML
    private TextField txtDbDriver;

    @FXML
    private TextField txtDbUserName;

    @FXML
    private TextField txtDbPwd;

    @FXML
    private TextField txtDbTabPre;//表名前缀

    @FXML
    private TextField sysName;

    @FXML
    private TextField sysNo;

    @FXML
    private TextField subSysName;

    @FXML
    private TextField projectNo;

    @FXML
    private ChoiceBox choiceBoxSchema;

    private Map<String,Object> params = new HashMap<>();

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:resources/conf/applicationContext.xml");
        schemaService = (SchemaService)context.getBean("schemaService");

        loadAllSchemas();
        choiceBoxSchema.getSelectionModel().selectFirst();
        //下拉框监听器，选择触发事件
        choiceBoxSchema.getSelectionModel().selectedItemProperty().addListener((ObservableValue observable, Object oldValue, Object newValue) -> {
            Schema schema = schemaService.findByName((String) newValue);
            if(schema == null) return;
            txtDbUrl.setText(schema.getUrl());
            txtDbDriver.setText(schema.getDriver());
            txtDbUserName.setText(schema.getUserName());
            txtDbPwd.setText(schema.getPassword());
            sysName.setText(schema.getSysName());
            sysNo.setText(schema.getSysNo());
            subSysName.setText(schema.getSubSysName());
            projectNo.setText(schema.getProjectNo());
        });

        //监听输入框在输入内容改变后清空查询信息
        addChangeListener(txtDbUrl);
        addChangeListener(txtDbDriver);
        addChangeListener(txtDbUserName);
        addChangeListener(txtDbPwd);
        addChangeListener(txtDbTabPre);

    }

    /**
     * 输入框添加监听内容变化的监听器
     * @param textField
     */
    private void addChangeListener(TextField textField) {
        textField.textProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                if(StringUtils.hasText(newValue)){
                    tables.setItems(null);
                }
            }
        });
    }

    /**
     * 下拉框加载模板
     */
    private void loadAllSchemas() {
        List<Schema> schemas = schemaService.findAll();
        choiceBoxSchema.getItems().clear();
        choiceBoxSchema.getItems().add("");
        for (Schema schema : schemas) {
            choiceBoxSchema.getItems().add(schema.getName());
        }
    }

    /**
     * 保存模板
     */
    @FXML
    public void saveSchema(){
        TextInputDialog dialog = new TextInputDialog();
        dialog.setTitle("输入模板名称");
        dialog.setHeaderText("模板名");
        dialog.setContentText("模板名称");
        Optional<String> result = dialog.showAndWait();
        if(StringUtils.hasText(result.get())){
            DBProperties dBProperties=readDbProperties();
            if(dBProperties == null) return;
            params.put("name",result.get());
            schemaService.saveSchema(dBProperties, params);
            loadAllSchemas();
        }else{
            Alert alert = new Alert(Alert.AlertType.INFORMATION,"模板名称必输！",new ButtonType("确定", ButtonBar.ButtonData.YES));
            alert.setTitle("校验未通过");
            alert.show();
        }


    }


    /**
     * 删除模板
     * @param actionEvent
     */
    public void deleteSchema(ActionEvent actionEvent) {
        String value = (String)choiceBoxSchema.getValue();
        if(!StringUtils.hasText(value)){
            Alert alert = new Alert(Alert.AlertType.INFORMATION,"未选择模板！",new ButtonType("确定", ButtonBar.ButtonData.YES));
            alert.setTitle("未选择模板");
            alert.show();
            return;
        }

        if(getConfirmAlert().get() == ButtonType.OK){
            schemaService.deleteSchemaByName(value);
            loadAllSchemas();
        }

    }

    /**
     *  弹出确认框
     * @return
     */
    private Optional<ButtonType> getConfirmAlert(){
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setTitle("确认");
        alert.setContentText("确定删除此条信息么");
        Optional<ButtonType> buttonType = alert.showAndWait();
        return buttonType;
    }


    /**
     * 读取用户输入的数据库连接信息
     * @return
     */
    @FXML
    public DBProperties readDbProperties(){
        String dbUrl=txtDbUrl.getText();
        Assert.notNull(dbUrl,"数据库连接地址不能为空");
        String dbDriver=txtDbDriver.getText();
        Assert.notNull(dbDriver,"数据库驱动不能为空！");
        String dbUserName=txtDbUserName.getText();
        Assert.notNull(dbUserName,"数据库用户名不能为空！");
        String dbPwd=txtDbPwd.getText();
        Assert.notNull(dbPwd,"数据库密码不能为空！");
        DBProperties db =new DBProperties(dbUrl,dbDriver,dbUserName,dbPwd);
        return db;
    }


    /**
     * 获取属性
     */
    private void getProperties(){
        params.put("sysName",sysName.getText());
        params.put("sysNo",sysNo.getText());
        params.put("projectNo",projectNo.getText());
        params.put("subSysName",subSysName.getText() == null ? "":subSysName.getText());
        params.put("txtDbTabPre",txtDbTabPre.getText() == null ? "":txtDbTabPre.getText());
    }

    /**
     * 获取需要生成的表，并保存到map中
     * @param dbProperties
     * @throws Exception
     */
    private void setTables(DBProperties dbProperties) throws Exception {
        ObservableList<TableInfo> selectedTabs = tables.getItems();
        Collections.sort(selectedTabs);
        params.put("tables",selectedTabs);
        String preText = txtDbTabPre.getText();
        if(StringUtils.hasText(preText)){
            List<TableInfo> tablesByPrefix = DBInfoService.getTablesByPrefix(preText, dbProperties);
            params.put("tables",tablesByPrefix);
        }

    }


    /**
     * 查询表结构数据
     * @param actionEvent
     */
    @FXML
    public void queryTableInfo(ActionEvent actionEvent) throws Exception {
        try{
            DBProperties dBProperties=readDbProperties();
            List<TableInfo> list= DBInfoService.getTables(dBProperties);
            System.out.println("查询到的表数量："+list.size());
            //将查询结构，添加到表格
            ObservableList<TableInfo> data = FXCollections.observableArrayList(list);
            id.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getRowIndex()));
            tableName.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getTableName()));
            chose.setCellValueFactory(cellData ->cellData.getValue().getCb().getCheckBox());
            tabConment.setCellValueFactory(cellData ->new SimpleStringProperty(cellData.getValue().getTableConment()));
            tables.setItems(data);
        } catch (Exception e){
            e.printStackTrace();
            AlertUtils.promoteErrorAlertDialog(e);
        }

    }


    /**
     * 导出到模板excel中
     * @param actionEvent
     */
    @FXML
    public void exportToModelExcel(ActionEvent actionEvent) {

        try{
            DBProperties dBProperties=readDbProperties();
            setTables(dBProperties);
            getProperties();
            exportDocument = new ExportDocumentForMultipleExcel(dBProperties, params);
            exportDocument.export();
            AlertUtils.promoteSuccessAlertDialog("导出成功！");
        } catch(Exception e){
            e.printStackTrace();
            AlertUtils.promoteErrorAlertDialog(e);
        }

    }

    /**
     * 导出到一个excel中
     * @param actionEvent
     */
    @FXML
    public void exportToExcel(ActionEvent actionEvent) {
        try{
            DBProperties dBProperties=readDbProperties();
            setTables(dBProperties);
            getProperties();
            exportDocument = new ExportDocumentForOneExcel(dBProperties, params);
            exportDocument.export();
            AlertUtils.promoteSuccessAlertDialog("导出成功！");
        } catch(Exception e){
            e.printStackTrace();
            AlertUtils.promoteErrorAlertDialog(e);
        }

    }

    /**
     * 导出到一个word文档
     * @param actionEvent
     */
    @FXML
    public void exportToWord(ActionEvent actionEvent) {
        try{
            DBProperties dBProperties=readDbProperties();
            setTables(dBProperties);
            getProperties();
            exportDocument = new ExportDocumentForWord(params, dBProperties);
            exportDocument.export();
            AlertUtils.promoteSuccessAlertDialog("导出成功！");
        } catch(Exception e){
            e.printStackTrace();
            AlertUtils.promoteErrorAlertDialog(e);
        }


    }



}
